#include "stdafx.h"
#include "out.h"

StdioOutputCallbacks::StdioOutputCallbacks (
	)
{
	InitializeCriticalSection( &m_OutputCS );
	m_ListFirst = NULL;
	m_ListLast = NULL;
}

StdioOutputCallbacks::~StdioOutputCallbacks (
	)
{
	DeleteCriticalSection( &m_OutputCS );
}

PStrList
StdioOutputCallbacks::GetOutput (
	)
{
	PStrList pResult = NULL;
	EnterCriticalSection( &m_OutputCS );

	if ( m_ListFirst )
	{
		pResult = m_ListFirst;
		m_ListFirst = m_ListFirst->m_pNext;

		if ( !m_ListFirst )
			m_ListLast = NULL;
	}

	LeaveCriticalSection( &m_OutputCS );
	
	return pResult;
}

STDMETHODIMP
StdioOutputCallbacks::QueryInterface(
    THIS_
    IN REFIID InterfaceId,
    OUT PVOID* Interface
    )
{
    *Interface = NULL;

    if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
        IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
    {
        *Interface = (IDebugOutputCallbacks *)this;
        AddRef();
        return S_OK;
    }
    else
    {
        return E_NOINTERFACE;
    }
}

STDMETHODIMP_(ULONG)
StdioOutputCallbacks::AddRef(
    THIS
    )
{
    // This class is designed to be static so
    // there's no true refcount.
    return 1;
}

STDMETHODIMP_(ULONG)
StdioOutputCallbacks::Release(
    THIS
    )
{
    // This class is designed to be static so
    // there's no true refcount.
    return 0;
}

STDMETHODIMP
StdioOutputCallbacks::Output (
    THIS_
    IN ULONG Mask,
    IN PCSTR Text
    )
{
	PStrList pOutput = (PStrList) HeapAlloc( GetProcessHeap(), 0, sizeof(StrList) );
	int len = lstrlenA(Text) + sizeof(CHAR);
	PCHAR pchString = (PCHAR) HeapAlloc( GetProcessHeap(), 0, len );
	if ( pOutput && pchString )
	{
		RtlZeroMemory( pOutput, sizeof(StrList) );
		pOutput->m_Flags = Mask;
		pOutput->m_String = pchString;

		RtlCopyMemory( pchString, Text, len );

		EnterCriticalSection( &m_OutputCS );

		if ( !m_ListLast )
		{
			m_ListFirst = pOutput;
			m_ListLast = pOutput;
		}
		else
		{
			m_ListLast->m_pNext = pOutput;
			m_ListLast = pOutput;
		}

		LeaveCriticalSection( &m_OutputCS );


		return S_OK;
	}
	
	if ( pOutput )
		HeapFree( GetProcessHeap(), 0, pOutput );

	if ( pchString )
		HeapFree( GetProcessHeap(), 0, pchString );

	return E_FAIL;
}
